/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fr.afcepf.projet2.metiers.donnees.dao.implementations;

import fr.afcepf.projet2.metiers.donnees.dao.interfaces.IDaoGeneric;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJBException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 * @see IDaoGeneric
 * @author Sylvain
 */
public abstract class DaoGenericImpl<T, PK extends Serializable> implements IDaoGeneric<T, PK> {

    private final Class<T> classeEntite;
    @PersistenceContext(name = "KingBoxIn-ejbPU")
    private EntityManager em;

    @SuppressWarnings("unchecked")
    public DaoGenericImpl() {
        this.classeEntite = (Class<T>) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public DaoGenericImpl(final Class<T> classeEntite) {
        super();
        this.classeEntite = classeEntite;
    }

    /**
     * @see IDaoGeneric#obtientClasseEntite()
     * @return
     */
    @Override
    public Class<T> obtientClasseEntite() {
        return classeEntite;
    }

    /**
     * @see IDaoGeneric#obtenirParId(java.io.Serializable)
     */
    @Override
    public T obtenirParId(final PK id) {
        try{
        T result = obtenirEntityManager().find(classeEntite, id);
       
        
        if (result != null) {
            return result;
        } else {
            try {
                return classeEntite.newInstance();
            } catch (InstantiationException | IllegalAccessException ex) {
                Logger.getLogger(DaoGenericImpl.class.getName()).log(Level.SEVERE, null, ex);
                return null;
            }
        }
         } catch (EJBException ex){
             System.out.println("EJBException");
             return null;
         }
    }

    /**
     * @see IDaoGeneric#rechercherParNamedQueryEtArguments(java.lang.String,
     * java.util.Map)
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<T> rechercherParNamedQueryEtArguments
            (final String namedQuery, Map<String, ? extends Object> args)
   throws EJBException {
        Query query = obtenirEntityManager().createNamedQuery(namedQuery);
        if (args != null) {
            for (final Map.Entry<String, ? extends Object> arg : args.entrySet()) {
                query.setParameter(arg.getKey(), arg.getValue());
            }
        }
        final List<T> result = (List<T>) query.getResultList();
        if (result != null) {
            return result;
        } else {
            return new ArrayList<>();
        }
    }
    
        /**
     * @see IDaoGeneric#rechercherParNamedQueryEtArguments(java.lang.String,
     * java.util.Map)
     */
    @Override
    @SuppressWarnings("unchecked")
    public List<T> rechercherParNamedQuery
            (final String namedQuery)
    throws EJBException {
        Query query = obtenirEntityManager().createNamedQuery(namedQuery);
        final List<T> result = (List<T>) query.getResultList();
        if (result != null) {
            return result;
        } else {
            return new ArrayList<>();
        }
    }

    /**
     * @see IDaoGeneric#supprimer(java.lang.Object)
     * // TODO Voir pour les exceptions
     */
    @Override
    public void supprimer(final T entite)throws EJBException{
        // On s'assure que l'entité passé en paramètre n'est pas nul
        // afin de ne pas perturber le test de vérification
        if (entite != null) {
            // On supprime l'entité
            obtenirEntityManager().remove(obtenirEntityManager().merge(entite));
        } else {
            // Aucune entité n'a été passée en paramètre
            System.out.println("Test pas d'argument ok");
          //  throw new DaoNoDataException();
        }
    }

    /**
     * @see IDaoGeneric#supprimerParId(java.io.Serializable)
     */
    @Override
    public void supprimerParId(final PK id) throws EJBException{
          T  entite = obtenirParId(id);
          supprimer(entite);
    }

    /**
     * @see IDaoGeneric#modifier(java.lang.Object)
     */
    @Override
    public void modifier(final T entite)throws EJBException{
        if (entite != null) {
            obtenirEntityManager().merge(entite);
        } else {
            // TODO Voir pour les exceptions
          //  throw new DaoNoDataException();
        }
    }

    /**
     * @see IDaoGeneric#modifierParId(java.io.Serializable)
     */
    @Override
    public void modifierParId(final PK id) throws EJBException{
        modifier(obtenirParId(id));
    }

    /**
     * @see IDaoGeneric#ajouter(java.lang.Object)
     */
    @Override
    public T ajouter(T entite) throws EJBException{
        if (entite != null) {
            obtenirEntityManager().persist(entite);
            obtenirEntityManager().flush();
            obtenirEntityManager().refresh(entite);
            return entite;
        } else {
            // TODO Voir pour les exceptions
          return null;
            // throw new DaoNoDataException();
        }
    }

    /**
     * @see IDaoGeneric#obtenirEntityManager()
     */
    @Override
    public EntityManager obtenirEntityManager()
             throws EJBException {
        return em;
    }
}
